package haxeframe.utils;

import haxe.Timer;
import haxeframe.Globals;

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.net.SharedObject;
import flash.utils.ByteArray;

class Utils
{
     private static var formatBitmapData:Array<String> = ['jpg','png'];
     private static var formatFont:Array<String> = ['ttf','otf'];
     private static var formatText:Array<String> = ['txt','xml','json'];
     private static var formatSound:Array<String> = ['mp3','ogg','wav','aif'];
     private static var formatMovieClip:Array<String> = ['swf'];

    static inline function base64Strings():Array<String> {
        return ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'];
    }

    static inline function base64Data():Array<Int> {
        return [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1];
    }

     public static function scaleBitmapData(bitmapData:BitmapData, scale:Float):BitmapData {
          scale = Math.abs(scale);
          var width:Int = Math.ceil(bitmapData.width * scale);
          var height:Int = Math.ceil(bitmapData.height * scale);
          var transparent:Bool = bitmapData.transparent;
          var result:BitmapData = new BitmapData(width, height, true, 0x000000);
          var matrix:Matrix = new Matrix();
          matrix.scale(scale, scale);
          result.draw(bitmapData, matrix);
          return result;
     }

     public static function removeChildren(s:Sprite):Void
     {
     	while(s.numChildren > 0){
     		s.removeChildAt(0);
     	}
     }

	public static function valueInArray(value:Dynamic, array:Array<Dynamic>):Bool
	{
		for(v in array){
			if(v == value)
			return true;
		}
		return false;
	}
#if !ios
     public static function encodeBase64(data:ByteArray):String {

        var out:Array<String> = [];
        var i:Int = 0;
        var j:Int = 0;
        var r:Int = data.length % 3;
        var len:Int = data.length - r;
        var c:Int;

        var chars:Array<String> = base64Strings();

        while (i < len) {
            c = data[i++] << 16 | data[i++] << 8 | data[i++];
            out[j++] = chars[c >> 18] + chars[c >> 12 & 0x3f] + chars[c >> 6 & 0x3f] + chars[c & 0x3f];
        }

         if (r == 1) {
             c = data[i++];
             out[j++] = chars[c >> 2] + chars[(c & 0x03) << 4] + "==";
         } else if (r == 2) {
             c = data[i++] << 8 | data[i++];
             out[j++] = chars[c >> 10] + chars[c >> 4 & 0x3f] + chars[(c & 0x0f) << 2] + "=";
         }

         return out.join('');
     }

     public static function decodeBase64Async(string:String, index:Int=0, byteArray:ByteArray=null, scope:Dynamic=null, callback:Array<Dynamic>->Void=null, params:Array<Dynamic>=null, rate:Int=1024):Void
     {
        for(i in 0...rate){
            if(byteArray != null){
                byteArray[index] = decodeBase64(string.charAt(index))[0];
            } else {
                byteArray = decodeBase64(string.charAt(index));
            }
            ++index;
            if(index >= string.length){
                break;
            }
        }
        if(index < string.length){
            Timer.delay(function():Void{
                decodeBase64Async(string, index, byteArray, scope, callback, params);
            }, 1);
        } else if(scope != null && callback != null){
            if(params == null) params = [];
            params.push(byteArray);
            Reflect.callMethod(scope, callback, [params]);
        }
     }

     public static function decodeBase64(string:String):ByteArray {

         var c1:Int;
         var c2:Int;
         var c3:Int;
         var c4:Int;
         var i:Int;
         var len:Int;
         var out:ByteArray;
         len = string.length;

        var chars:Array<Int> = base64Data();

         i = 0;
         out = new ByteArray();
         while (i < len) {

            // c1
             do {
                c1 = chars[string.charCodeAt(i++) & 0xff];
             } while (i < len && c1 == -1);
             if (c1 == -1) {
                break;
             }

             // c2
             do {
                c2 = chars[string.charCodeAt(i++) & 0xff];
             } while (i < len && c2 == -1);
             if (c2 == -1) {
                break;
             }
             out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4));

             // c3
             do {
                c3 = string.charCodeAt(i++) & 0xff;
                 if (c3 == 61) {
                    return out;
                 }
                 c3 = chars[c3];
             } while (i < len && c3 == -1);
             if (c3 == -1) {
                break;
             }
             out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2));

             // c4
             do {
                c4 = string.charCodeAt(i++) & 0xff;
                 if (c4 == 61) {
                    return out;
                 }
                c4 = chars[c4];
             } while (i < len && c4 == -1);
             if (c4 == -1) {
                break;
             }
            out.writeByte(((c3 & 0x03) << 6) | c4);
        }
        return out;
     }
     #end
}